/*
 * DAGYRUSS for PC-FXGA
 */
#define ASL_USE_MACRO

#include	<system.h>
#include	<v93.h>
#include	<nt.h>
#include	<soundbox.h>
#include	<adp.h>
#include	<farl.h>
#include	<agl.h>
#include	<asl.h>
#include	<common.h>
#include	<libm.h>
#include	<intlib.h>
#include	<pio.h>

// ADPCMファイルヘッダーチェック用
#define ID_RIFF 'FFIR'
#define ID_WAVE 'EVAW'
#define ID_FMT  ' tmf'

#define Sin8(angle)                SinTable8[(angle) & 0xff]
#define Cos8(angle)                SinTable8[((angle) & 0xff)+64]

#define	DAR_SHIP	256+4
#define	DAR_BAKU	256+24
#define	DAR_ZAKO	256+0
#define	DAR_WHITE	256+63
#define	DAR_SHOT	256+64
#define DAR_BOSS	256+64+16
#define	DAR_NEC		256+64+16+1
#define	DAR_BIO		256+64+16+2
#define	DAR_EMI0	256+64+16+2+1
#define	DAR_EMI1	256+64+16+2+2

#define	ADP_1UP			0
#define	ADP_BBAKU		1
#define	ADP_COIN		2
#define	ADP_DAMAGE		3
#define	ADP_HITCOMBO	4
#define	ADP_ITEM		5
#define	ADP_LSHOT		6
#define	ADP_NSHOT		7
#define	ADP_ROCK		8
#define	ADP_WSHOT		9
#define	ADP_ZBAKU		10

#define	MAXCHAR		1024
#define	MAXSCT		2048
#define	FADERATE	64
#define	MAXXSPEED	20
#define	MAXYSPEED	20
#define	MAXMSL		4
#define	MAXENEMY	7
#define	MAXENEMYMSL	4
#define	MAXHOMING	2
#define	MAXSTAR		20
#define	MAXITEM		2
#define	MAXSTAGE	13
#define	MAXCOUNT	500
#define	MAXBAKU		10
#define	MAXPCM		11
#define	MAXKING		3

#define	OX			128
#define	OY			112
#define	YRATE		256
#define	MAXY		1900

int SinTable8[256+64] = {
	    0,   6,  13,  19,  25,  31,  38,  44,
	   50,  56,  62,  68,  74,  80,  86,  92,
	   98, 104, 109, 115, 121, 126, 132, 137,
	  142, 147, 152, 157, 162, 167, 172, 177,
	  181, 185, 190, 194, 198, 202, 206, 209,
	  213, 216, 220, 223, 226, 229, 231, 234,
	  237, 239, 241, 243, 245, 247, 248, 250,
	  251, 252, 253, 254, 255, 255, 256, 256,

/* _CosTable8 */
	  256, 256, 256, 255, 255, 254, 253, 252,
	  251, 250, 248, 247, 245, 243, 241, 239,
	  237, 234, 231, 229, 226, 223, 220, 216,
	  213, 209, 206, 202, 198, 194, 190, 185,
	  181, 177, 172, 167, 162, 157, 152, 147,
	  142, 137, 132, 126, 121, 115, 109, 104,
	   98,  92,  86,  80,  74,  68,  62,  56,
	   50,  44,  38,  31,  25,  19,  13,   6,

	    0,  -6, -13, -19, -25, -31, -38, -44,
	  -50, -56, -62, -68, -74, -80, -86, -92,
	  -98,-104,-109,-115,-121,-126,-132,-137,
	 -142,-147,-152,-157,-162,-167,-172,-177,
	 -181,-185,-190,-194,-198,-202,-206,-209,
	 -213,-216,-220,-223,-226,-229,-231,-234,
	 -237,-239,-241,-243,-245,-247,-248,-250,
	 -251,-252,-253,-254,-255,-255,-256,-256,

	 -256,-256,-256,-255,-255,-254,-253,-252,
	 -251,-250,-248,-247,-245,-243,-241,-239,
	 -237,-234,-231,-229,-226,-223,-220,-216,
	 -213,-209,-206,-202,-198,-194,-190,-185,
	 -181,-177,-172,-167,-162,-157,-152,-147,
	 -142,-137,-132,-126,-121,-115,-109,-104,
	  -98, -92, -86, -80, -74, -68, -62, -56,
	  -50, -44, -38, -31, -25, -19, -13,  -6,

	    0,   6,  13,  19,  25,  31,  38,  44,
	   50,  56,  62,  68,  74,  80,  86,  92,
	   98, 104, 109, 115, 121, 126, 132, 137,
	  142, 147, 152, 157, 162, 167, 172, 177,
	  181, 185, 190, 194, 198, 202, 206, 209,
	  213, 216, 220, 223, 226, 229, 231, 234,
	  237, 239, 241, 243, 245, 247, 248, 250,
	  251, 252, 253, 254, 255, 255, 256, 256
	};

unsigned long pcmblock = 0L;
unsigned char pcmbuffer[65000];

// ADPファイルヘッダー用構造体
typedef struct adpfileheader_t{
	unsigned long   afFileID;             // RIFF
	unsigned long   afFileSize;
	unsigned long   afFileType;           // WAVE
	unsigned long   afFormatID;           // fmt
	unsigned long   afFormatSize;
	unsigned short  afFormatType;         // フォーマットタイプ
	unsigned short  afNumberOfChannel;    // チャンネル数
	unsigned long   afSamplingRate;       // サンプリングレート
	unsigned long   afTransferByte;       // 転送レート
	unsigned short  afSampleCount;        // サンプル数
	unsigned short  afBitOfNumber;        // 量子化ビット
	unsigned long   afDataID;             // データＩＤ
	unsigned long   afDataSize;           // データサイズ
	}ADPFILEHEAD;
ADPFILEHEAD     aFileHead[MAXPCM];
struct PCMINFO  pInfo[MAXPCM];
struct PCMVOL	pcmvol;

ASLSct		sct;
ASLSource	src[MAXCHAR];
unsigned short  buf[163840];
unsigned short	workdat[512];
unsigned short  KingFile[MAXKING][130000];

int	aflag = 0;
int	charnumber = 0;
unsigned int randomseed;	// seed
int	stage = 0;
int	loop = 0;
int	gamecount = 0;
int	gamex,gamey,gametype;
int	hit = 0;
int hit2 = 0;
int	hitcount = 0;
int	tspeed = 15;
int	shotrate = 100;
int	stagecount;
int	highscore = 0;
int	bossflag = 0;
int	stagemesscount;
int	stagedat[MAXSTAGE]={
	50, 60, 1, 60, 60, 50, 70, 70, 1, 80, 80, 50, 1};
int	oscore;
int	left;
int	shotready;
int	onehit;
int	stageclearcount;
int	pauseflag = 0;
int	pcmch = 0;
int	maxhit = 0;
int	overcount = 0;
int	skipflag = 0;

/* 自機 */
struct	status{
	int	x;
	int	y;
	int	x2;
	int	y2;
	int	xspeed;
	int	yspeed;
	int	xsize;
	int	ysize;
	int	pat;
	int	type;
	int	mtype;
	int	flag;
	int	mcount;
	int	mcount2;
	int	muteki;
	int	hp;
	int	score;
	}ship;

struct status msl[MAXMSL];
struct status enemy[MAXENEMY];
struct status enemymsl[MAXENEMYMSL];
struct status homing[MAXHOMING][10];
struct status star[MAXSTAR];
struct status item[MAXITEM];
struct status baku[MAXBAKU];

extern unsigned short i5c4yuv_col[];

void main (void);
void gamemain (void);
void stageclear (void);
void hedload (int bank, unsigned char *filename);
void srcset (unsigned short bank, int xsize, int ysize, int xnum, int ynum);
void InitSystem (void);
void InitScreen (void);
void sprput (int x, int y, int r, int z, int pat);
void dspwait (void);
void shipcontrol (void);
void shipinit (void);
void shipdsp (void);
void mslinit (void);
void mslcontrol (void);
void iteminit (int num);
void itemcontrol (void);
void enemyinit (void);
void enemycontrol (void);
void bosscontrol (void);
void enemymslcontrol (void);
void enemyshot(int x1,int y1,int x2,int y2);
void enemyshot2(int x,int y,int xs,int ys);
void hominginit (int num);
void homingcontrol (void);
void starcontrol (void);
void writetex (int bank, int x, int y, int data);
int random(int num);
int hitcheck(int x1,int y1,int sx1,int sy1,int x2,int y2,int sx2,int sy2);
void getgametype (void);
void move0(int mode, int num);
void move1(int mode, int num);
void move2(int mode, int num);
void move3(int mode, int num);
void move4(int mode, int num);
void move5(int mode, int num);
void move6(int mode, int num);
void move7(int mode, int num);
void move8(int mode, int num);
void move9(int mode, int num);
void move10(int mode, int num);
void StrDsp(int x,int y,unsigned char *str);
void NumDsp(int x,int y,unsigned long val);
int enemybakucheck (void);
void bakuinit(int mode,int num);
void bakucontrol(void);
int onehitcheck(void);
void title(void);
void kingload(int bgnum, unsigned char *filename);
void kingdsp(int num);
int adpload(int num, unsigned char *filename);
void pcmplay(int num);
void PaletteChange(int palettenumber, unsigned short yuv);
void PaletteChangeBW(int mode, int start, int end);
void PaletteFadeBlack(int mode, int start, int end);
void PaletteFadeWhite(int mode, int start, int end);
void Wait(int c);
void logodsp();
void MakePaletteDataBlack(int i, int j);
void MakePaletteDataWhite(int i, int j);
void ending(void);
void fishinit(void);
void fishdsp(void);

/*
 * メイン
 */
void
main()
	{
	int	i,j,c,d,e,f,g,espeed;
	int	xx,yy;
	int	pp = 0;

	// 初期化
	cache_enable();                               // キャッシュ開始
	DevInit();                                    // 各種デバイス初期化
	InitSystem();
	InitScreen();
	FX73init();
	FX73_cmap_i5c4();
	FarlInit();
	// もう一度初期化しないとADPCMか色がおかしくなる
	DevInit();
	InitSystem();

	AdpcmVolume(CHANNEL_1, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MIN_PCM_VOLUME, MIN_PCM_VOLUME);
	AdpcmInit();
	AdpcmVolume(CHANNEL_1, MAX_PCM_VOLUME, MAX_PCM_VOLUME);
	AdpcmVolume(CHANNEL_2, MAX_PCM_VOLUME, MAX_PCM_VOLUME);

	pcmvol.pvoll = 0x28;
	pcmvol.pvolr = 0x28;
	set_pcm_vol(&pcmvol);

	KINGScreen(0);								// 画面モード16m色
	KINGDispOff();								// HuC6272 表示オフ
	KINGCylinder(KING_BG0,1);					// 茶筒モード
	KINGChangeSize0(DISP_NORMAL);				// 画面幅設定
	dispoff(bg | spr | rain | bg1 | bg2 | bg3);	// 他画面オフ
	dispon(bg | spr | bg0);						// 画面ON
	KINGCls(KING_BG0);							// 画面消去
	KINGDispOff();								// HuC6272 表示オン

	VSyncInt();
	charnumber = 0;

	// スプライトが表示される領域の設定
	ASLSetSpriteWindow( 0, 0, 255, 239 );

	// Sprite Data Load
	hedload(13,"HTJFONT.HED");
	StrDsp(16,218,"Now Loading...1/9");
	dspwait();
	hedload(0,"DAGY00.HED");
	StrDsp(16,218,"Now Loading...2/9");
	dspwait();
	hedload(1,"DAGY01.HED");
	StrDsp(16,218,"Now Loading...3/9");
	dspwait();
	hedload(2,"DAGY02.HED");
	StrDsp(16,218,"Now Loading...4/9");
	dspwait();
	hedload(3,"LOGO.HED");
	StrDsp(16,218,"Now Loading...5/9");
	dspwait();
	hedload(4,"EMI.HED");

	// BG Data Load
	StrDsp(16,218,"Now Loading...6/9");
	dspwait();
	kingload(0,"SPACE02.BIN");	// normal
	StrDsp(16,218,"Now Loading...7/9");
	dspwait();
	kingload(1,"SPACE01.BIN");	// Challenging stage
	StrDsp(16,218,"Now Loading...8/9");
	dspwait();
	kingload(2,"SPACE00.BIN");	// Title

	// ADPCM Data Load
	StrDsp(16,218,"Now Loading...9/9");
	dspwait();
	adpload(0,"1UP.ADP");
	adpload(1,"BBAKU.ADP");
	adpload(2,"COIN.ADP");
	adpload(3,"DAMAGE.ADP");
	adpload(4,"HITCOMBO.ADP");
	adpload(5,"ITEM.ADP");
	adpload(6,"LSHOT.ADP");
	adpload(7,"NSHOT.ADP");
	adpload(8,"ROCK.ADP");
	adpload(9,"WSHOT.ADP");
	adpload(10,"ZBAKU.ADP");

	skipflag = 0;
	logodsp();
	dspwait();
	KINGDispOn();                                 // HuC6272 表示オン
	FX73_cmap_i5c4();
	title();
	}

/*
 * ゲームメイン
 */
void
gamemain()
	{
	int	i,a,b;

	shipinit();
	aflag = 0;
	get_pad();

	FX73_cmap_i5c4();

	stagemesscount = 150;
	shotrate = 500 - stage*20 - loop*250;
	if ( shotrate <= 0 ) shotrate = 1;
	gamecount = 1;
	gamex = random(2560);
	getgametype();
	stagecount = stagedat[stage];
	onehit = 0;
	oscore = ship.score;
	ship.mtype = ship.type;
	if ( stage == 2 || stage == 8 )
		{
		ship.mtype = 0;
		shotready = 0;
		}
	else
		{
		shotready = 1;
		}
	get_pad();
	// メインループ
	while(1)
		{
		if ( pauseflag )
			{
			// 一時停止
			while(1)
				{
				get_pad();
				if ( pad00.KD_TRG & KP_run )
					{
					pauseflag = 0;
					break;
					}
				}
			}
		stagemesscount--;
		if ( stagemesscount <= 0 )
			{
			stagemesscount = 0;
			shotready = 1;
			}
		hitcount--;
		if ( hitcount < 0 ) hitcount = 0;
		if ( enemybakucheck() == 0 )
			{
			if ( hit > 1 )
				{
				hitcount = 30;
				hit2 = hit;
				ship.score += hit2 * hit2 * 10;
				if ( maxhit < hit2 ) maxhit = hit2;
				if ( hit2 > 7 ) pcmplay(ADP_HITCOMBO);
				}
			hit = 0;
			}
		aflag++;
		if ( aflag > 15 )
			{
			aflag = 0;
			gamecount--;
			if ( gamecount <= 0 )
				{
				gamecount = random(5) + 1;
				gamex = random(2560);
				getgametype();
				}
			if ( stagecount > 0 && stagemesscount == 0 )
				{
				enemyinit();
				stagecount--;
				}
			if ( stagecount <= 0 )
				{
				stagecount = 0;
				a = 0;
				for ( i = 0 ; i < MAXENEMY ; i++ )
					{
					if ( enemy[i].flag ) break;
					a++;
					}
				b = 0;
				for ( i = 0 ; i < MAXBAKU ; i++ )
					{
					if ( baku[i].flag ) break;
					b++;
					}
				if ( a == MAXENEMY && b == MAXBAKU )
					{
					for ( i = 0 ; i < MAXENEMY ; i++ )
						{
						enemymsl[i].flag = 0;
						}
					shotready = 0;
					if ( overcount == 0 ) stageclearcount++;
					if ( stageclearcount > 15 ) stageclear();
					}
				}
			}
		starcontrol();
		shipcontrol();
		mslcontrol();
		if ( bossflag )
			{
			bosscontrol();
			}
		else
			{
			enemycontrol();
			}
		enemymslcontrol();
		homingcontrol();
		itemcontrol();
		bakucontrol();
		shipdsp();
		dspwait();
		}
	}

/*
 * Stage Clear
 */
void
stageclear()
	{
	if ( stage == 2 || stage == 8 )
		{
		if ( onehitcheck() )
			{
			pcmplay(ADP_1UP);
			left++;
			}
		}
	else if ( stage == 5 || stage == 11 )
		{
		pcmplay(ADP_1UP);
		left++;
		}
	stage++;
	if ( stage >= MAXSTAGE )
		{
		ending();
		skipflag = 0;
		logodsp();
		dspwait();
		KINGDispOn();
		FX73_cmap_i5c4();
		title();
		}
	gamemain();
	}

/*
 * HEDファイルの読み込み
 */
void
hedload(int bank,unsigned char *filename)
	{
	int	fp, c,i,j;
	int	p,q,r,s;

	pio_putstr( "HED Data Loading..." );
	// 読み込み
	fp = pio_fopen(filename, "rb" );
	if ( fp == -1 )
		{
		pio_putstr( "\nCannot Open HED File.\n" );
		return;
		}
//	c = (256*256+4) * 2;
	c = 8;
	pio_fread(fp,c,(char *)buf);
	c = 0;
	p = buf[c];
	c++;
	q = buf[c];
	c++;
	r = buf[c];
	c++;
	s = buf[c];

	c = (p*r*q*s) * 2;
	pio_fread(fp,c,(char *)buf);
	c = 0;
	for ( i = 0 ; i < q*s ; i++ )
		{
		for ( j = 0 ; j < p*r ; j++ )
			{
			writetex(bank,j,i,buf[c]);
			c++;
			}
		}
	srcset(bank,p,q,r,s);
	pio_putstr( "done.\n" );
	pio_fclose(fp);
	return;
	}

/*
 * パターン情報セット
 */
void
srcset(unsigned short bank, int xsize, int ysize, int xnum, int ynum)
	{
	int	i,j,n;

	for ( i = 0 ; i < ynum ; i++ )
		{
		for ( j = 0 ; j < xnum ; j++ )
			{
			src[charnumber].bank   = bank;
			src[charnumber].x_pos  = j*xsize;
			src[charnumber].y_pos  = i*ysize;
			src[charnumber].x_size = xsize;
			src[charnumber].y_size = ysize;
			src[charnumber].x_hot  = xsize/2;
			src[charnumber].y_hot  = ysize/2;
			charnumber++;
			}
		}
	}

/*
 * システム初期化
 */
void
InitSystem()
	{
	irq_disable();
	cache_clear();
	cache_enable();
    set_irq_mask(
		BIT_IRQM_SIO | 
		BIT_IRQM_7A | 
		BIT_IRQM_7B |
		BIT_IRQM_KING |
		BIT_IRQM_KP |
		BIT_IRQM_EXT |
		BIT_IRQM_TMI |
		BIT_IRQM_AERR |
		0
		);

	set_irq_prio(IRQ_PRIOA, IRQ_KP);
	set_irq_vector(&int_pad, IRQ_LEVELA);

    reset_irq_mask(
//			BIT_IRQM_SIO | 
//			BIT_IRQM_7A | 
//			BIT_IRQM_7B |
//			BIT_IRQM_KING |
			BIT_IRQM_KP |
//			BIT_IRQM_EXT |
//			BIT_IRQM_TMI |
//			BIT_IRQM_AERR |
			0
		);

	set_irq_level(0x0007);
	IrqOn(XINT_72);                /* HuC6272 割り込みを有効に */
	irq_enable();
	init_get_pad();
	get_pad();
	}

/*
 * 画面初期化
 */
void
InitScreen()
	{
	int i;

	init_nt();	// init Hu6261 device
	init_70();
	dispon(bg | spr | bg0 | bg1 | bg2 | bg3 | rain );
	dispoff( /*bg | spr |*/ bg0 | bg1 | bg2 | bg3 | rain );
	set_nt_mode(interlace | inter_sync | mode_5M | mode_sp256 | mode_bg256);

	cel_off(bg);
	cel_off(spr);
	cel_off(bg0);
	cel_off(bg1);
	cel_off(bg2);
	cel_off(bg3);
	cel_off(rain);
	}

/*
 * スプライト表示
 */
void
sprput(int x,int y,int r,int z,int pat)
	{
	if ( r == 0 && z == 256 )
		{
		// 普通のスプライトのSCTを作成する
		ASLMakeSimpleSprite( &src[pat], x, y, &sct);
		}
	else
		{
		// 拡大・縮小・回転の SCT を生成する(重たい)
		ASLMakeZoomRotateSprite( &src[pat], x, y, r, z, &sct );
		}
	// SCTをテクスチャ・バッファに書き込む
	ASLSetSpriteTable( 15, 0, 1, &sct );
	// SCTを実行する
	ASLExecuteSprite( 15, 0, 1);
	}

/*
 * 描画後処理
 */
void
dspwait()
	{
	// 描画終了待ち
	ASLSync();
	// ディスプレイバッファのスワップ(フリップ)
	FarlSwapWindow();
	// スワップ(フリップ)待ち
	ASLWaitForSwap();
	}

/*
 * プレイヤー移動
 */
void
shipcontrol()
	{
	int	i,a,b;

	if ( overcount > 0 )
		{
		overcount++;
		if ( overcount > 600 ) title();
		get_pad();
		if ( pad00.KD_TRG & KP_run || pad00.KD_TRG & KP_1 )
			{
			if ( overcount > 100 ) title();
			}
		return;
		}
	if ( ship.flag > 1 )
		{
		if ( aflag%4 == 0 )
			{
			ship.flag++;
			if ( ship.flag > 9 )
				{
				ship.y = 2000;
				ship.y2 = ship.y / 10;
				left--;
				if ( left < 0 )
					{
					left = 0;
					overcount = 1;
					ship.flag = 0;
					}
				else
					{
					ship.flag = 1;
					ship.muteki = 100;
					}
				}
			}
		return;
		}
	ship.muteki--;
	if ( ship.muteki <= 0 ) ship.muteki = 0;
	get_pad();

	if ( stageclearcount > 10 )
		{
		shotready = 0;
		ship.y -= 20;
		if ( ship.y < 200 ) ship.y = 200;
		}
	if ( ship.muteki > 0 )
		{
		ship.y -= 8;
		if ( ship.y <= 1600 ) ship.y = 1600;
		}

	if ( pad00.KD_DAT & KP_left )
		{
		ship.x -= MAXXSPEED;
		if ( ship.x < 0 ) ship.x += 2560;
		}
	else if ( pad00.KD_DAT & KP_right )
		{
		ship.x += MAXXSPEED;
		if ( ship.x > 2559 ) ship.x -= 2560;
		}
	if ( pad00.KD_TRG & KP_run )
		{
		pauseflag = 1;
		}
	if ( pad00.KD_DAT & KP_1 && shotready && onehit == 0 )
		{
		if ( ship.mtype == 0 )
			{
			if ( aflag%6 == 0 )
				{
				if ( stage == 2 || stage == 8 )
					{
					onehit = 1;
					}
				mslinit();
				}
			}
		else if ( ship.mtype == 1 )
			{
			a = 0;
			for ( i = 0 ; i < 4 ; i++ )
				{
				if ( msl[i].flag != 0 ) break;
				a++;
				}
			if ( a == 4 )
				{
				if ( stage == 2 || stage == 8 )
					{
					onehit = 1;
					}
				mslinit();
				}
			}
		else if ( ship.mtype == 2 )
			{
			if ( stage == 2 || stage == 8 )
				{
				onehit = 1;
				}
			mslinit();
			}
		}
	ship.x2 = ship.x / 10;
	ship.y2 = ship.y / 10;
	}

/*
 * 自機初期化
 */
void
shipinit()
	{
	int	i,j;

	stageclearcount = 0;
	ship.muteki = 100;
	ship.flag = 1;
	ship.x = 1920;
//	ship.y = 1600;
	ship.y = 2000;
	ship.x2 = 192;
	ship.y2 = 160;
	ship.pat = DAR_SHIP;
	ship.xsize = 320;
	ship.ysize = 320;
	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		msl[i].flag = 0;
		}
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		enemy[i].flag = 0;
		}
	for ( i = 0 ; i < MAXENEMYMSL ; i++ )
		{
		enemymsl[i].flag = 0;
		}
	for ( i = 0 ; i < MAXHOMING ; i++ )
		{
		for ( j = 0 ; j < 10 ; j++ )
			{
			homing[i][j].flag = 0;
			}
		}
	for ( i = 0 ; i < MAXSTAR ; i++ )
		{
		star[i].x = random(2560);
		star[i].y = 200;
		star[i].xspeed = 0;
		star[i].yspeed = random(20)+10;
		star[i].pat = DAR_SHOT + 8;
		}
	for ( i = 0 ; i < MAXITEM ; i++ )
		{
		item[i].flag = 0;
		}
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		baku[i].flag = 0;
		}
	dspwait();
	if ( stage == 2 || stage == 5 || stage == 8 || stage == 11 )
		{
		kingdsp(1);
		}
	else
		{
		kingdsp(0);
		}
	}

/*
 * 自機関係表示
 */
void
shipdsp()
	{
	int	i,j,a;
	int	xx,yy,rr,dd;

	// Star
	for ( i = 0 ; i < MAXSTAR ; i++ )
		{
		rr = star[i].y2 * star[i].y2 / YRATE;
		xx = rr * Cos8(star[i].x2) / 256 + OX;
		yy = OY - rr * Sin8(star[i].x2) / 256;
		sprput(xx,yy,0,256,star[i].pat);
		}
	// Missle
	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag )
			{
			rr = msl[i].y2 * msl[i].y2 / YRATE;
			xx = rr * Cos8(msl[i].x2) / 256 + OX;
			yy = OY - rr * Sin8(msl[i].x2) / 256;
			dd = (3600 * (255-msl[i].x2) / 256 - 900)%3600;
			sprput(xx,yy,dd,rr*3,msl[i].pat);
			}
		}
	// Enemy Missle
	for ( i = 0 ; i < MAXENEMYMSL ; i++ )
		{
		if ( enemymsl[i].flag )
			{
			rr = enemymsl[i].y2 * enemymsl[i].y2 / YRATE;
			xx = rr * Cos8(enemymsl[i].x2) / 256 + OX;
			yy = OY - rr * Sin8(enemymsl[i].x2) / 256;
			dd = (3600 * (255-enemymsl[i].x2) / 256 - 900)%3600;
			sprput(xx,yy,dd,rr*3,enemymsl[i].pat);
			}
		}
	// Homing
	for ( i = 0 ; i < MAXHOMING ; i++ )
		{
		for ( j = 9 ; j >= 0 ; j-=3 )
			{
			if ( homing[i][j].flag )
				{
				rr = homing[i][j].y2 * homing[i][j].y2 / YRATE;
				xx = rr * Cos8(homing[i][j].x2) / 256 + OX;
				yy = OY - rr * Sin8(homing[i][j].x2) / 256;
				dd = (3600 * (255-homing[i][j].x2) / 256 - 900)%3600;
				sprput(xx,yy,dd,rr*3,homing[i][j].pat);
				}
			}
		}
	// 敵
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			rr = enemy[i].y2 * enemy[i].y2 / YRATE;
			xx = rr * Cos8(enemy[i].x2) / 256 + OX;
			yy = OY - rr * Sin8(enemy[i].x2) / 256;
			dd = (3600 * (255-enemy[i].x2) / 256 - 900)%3600;
			if ( enemy[i].flag > 1 )
				{
				sprput(xx,yy,dd,rr*3,DAR_BAKU+enemy[i].flag-2);
				}
			else if ( enemy[i].flag == 1 )
				{
				if ( enemy[i].muteki == 0 || aflag%2 == 0 )
					{
					sprput(xx,yy,dd,rr*3,enemy[i].pat);
					}
				}
			}
		}
	// BAKU
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			rr = baku[i].y2 * baku[i].y2 / YRATE;
			xx = rr * Cos8(baku[i].x2) / 256 + OX;
			yy = OY - rr * Sin8(baku[i].x2) / 256;
			dd = (3600 * (255-baku[i].x2) / 256 - 900)%3600;
			sprput(xx,yy,dd,rr*3,baku[i].pat+baku[i].flag-2);
			}
		}
	// Item
	for ( i = 0 ; i < MAXITEM ; i++ )
		{
		if ( item[i].flag )
			{
			rr = item[i].y2 * item[i].y2 / YRATE;
			xx = rr * Cos8(item[i].x2) / 256 + OX;
			yy = OY - rr * Sin8(item[i].x2) / 256;
			dd = (3600 * (255-item[i].x2) / 256 - 900)%3600;
			sprput(xx,yy,dd,rr*3,item[i].pat);
			}
		}
	// 自機の表示
	rr = ship.y2 * ship.y2 / YRATE;
	xx = rr * Cos8(ship.x2) / 256 + OX;
	yy = OY - rr * Sin8(ship.x2) / 256;
	dd = (3600 * (255-ship.x2) / 256 - 900)%3600;
	if ( ship.flag > 1 )
		{
		sprput(xx,yy,dd,rr*3,DAR_BAKU+8+ship.flag-2);
		}
	else if ( ship.flag == 1 && (ship.muteki == 0 || aflag%2 == 0) )
		{
		sprput(xx,yy,dd,rr*3,ship.pat);
		}
	if ( hitcount > 0 )
		{
		StrDsp(160,26,"HIT");
		NumDsp(192,26,hit2);
		if ( hit2 > 4 && hit2 < 7 ) StrDsp(208,26,"NICE!");
		if ( hit2 > 6 ) StrDsp(208,26,"GREAT!");
		}
	if ( stagemesscount > 0 )
		{
		if ( stage == 2 || stage == 8 )
			{
			StrDsp(60,112,"CHALLENGING STAGE");
			StrDsp(60,136,"- ｲｯﾊﾟﾂ ﾃﾞ ｼﾄﾒﾖ -");
			}
		else if ( stage == 5 || stage == 11 )
			{
			StrDsp(60,112,"CHALLENGING STAGE");
			StrDsp(60,136,"- ｲﾝｾｷ ｦ ﾖｹﾙﾉﾀﾞ -");
			}
		else
			{
			StrDsp(100,112,"STAGE");
			NumDsp(146,112,stage+1);
			}
		}
	if ( stageclearcount > 0 && overcount == 0 )
		{
		if ( stage == 2 || stage == 8 )
			{
			if ( onehitcheck() )
				{
				StrDsp(90,112," BONUS 1UP ");
				}
			else
				{
				StrDsp(90,112," NO BONUS  ");
				}
			}
		else if ( stage == 5 || stage == 11 )
			{
			StrDsp(90,112," BONUS 1UP ");
			}
		else
			{
			StrDsp(90,112,"STAGE CLEAR");
			}
		}
	if ( overcount > 0 )
		{
		StrDsp(72,100,"G A M E  O V E R");
		StrDsp(80,160,"SCORE :");
		NumDsp(144,160,ship.score);
		StrDsp(80,176,"MAX HIT :");
		NumDsp(160,176,maxhit);
		}
	else
		{
		// SCORE
		StrDsp(160,16,"SCORE");
		NumDsp(208,16,ship.score);
		StrDsp(16,16,"LEFT");
		NumDsp(56,16,left);
		}
	}

/*
 * Missle Initialize
 */
void
mslinit()
	{
	int	i,j;

	if ( ship.mtype == 0 )
		{
		for ( i = 0 ; i < MAXMSL ; i++ )
			{
			if ( msl[i].flag == 0 )
				{
				msl[i].flag = 1;
				msl[i].pat = DAR_SHOT+1;
				msl[i].x = ship.x;
				msl[i].y = ship.y;
				msl[i].xsize = 160;
				msl[i].ysize = 320;
				msl[i].type = 0;
				msl[i].yspeed = 50;
				// pcmplay(0);
				break;
				}
			}
		}
	else if ( ship.mtype == 1 )
		{
		for ( j = 0 ; j < 4 ; j++ )
			{
			for ( i = 0 ; i < MAXMSL ; i++ )
				{
				if ( msl[i].flag == 0 )
					{
					msl[i].flag = 1;
					msl[i].pat = DAR_SHOT;
					msl[i].x = ship.x-150 + j*100;
					msl[i].y = ship.y;
					msl[i].xsize = 160;
					msl[i].ysize = 320;
					msl[i].type = 1;
					msl[i].yspeed = 40;
					// pcmplay(0);
					break;
					}
				}
			}
		}
	else if ( ship.mtype == 2 )
		{
		for ( i = 0 ; i < MAXMSL ; i++ )
			{
			if ( msl[i].flag == 0 )
				{
				msl[i].flag = 1;
				msl[i].pat = DAR_SHOT+7;
				msl[i].x = ship.x;
				msl[i].y = ship.y;
				msl[i].xsize = 160;
				msl[i].ysize = 320;
				msl[i].type = 2;
				msl[i].yspeed = 40;
				// pcmplay(0);
				break;
				}
			}
		}
	}

/*
 * Ship Missle Control
 */
void
mslcontrol()
	{
	int	i;

	for ( i = 0 ; i < MAXMSL ; i++ )
		{
		if ( msl[i].flag )
			{
			msl[i].y -= msl[i].yspeed;
			if ( msl[i].y < 200 ) msl[i].flag = 0;
			msl[i].x2 = msl[i].x / 10;
			msl[i].y2 = msl[i].y / 10;
			}
		}
	}

/*
 * write texure buffer
 */
void
writetex(int bank, int x, int y, int data)
	{
	FarlSetMemReg(FARL_CMT_BANK_SELECT_REG, bank);
	FarlWriteTxtXYUnpk(x, y, data);
	}

/*
 * 乱数発生
 */
int
random(int num)
	{
	unsigned int a;

	randomseed = randomseed * 1103515245 + 12345;
	a = (randomseed/0x10000) % 0x8000;
	a %= num;
	return a;
	}

/*
 * 当たり判定
 */
int
hitcheck(int x1,int y1,int sx1,int sy1,int x2,int y2,int sx2,int sy2)
	{
	int	a,b,c,d;

	a = sx1 / 2;
	b = sy1 / 2;
	c = sx2 / 2;
	d = sy2 / 2;

	if ( x1 < x2 )
		{
		if ( y1 < y2 )
			{
			if ( (a + c > x2 - x1) && (b + d > y2 - y1) )
				{
				return	1;
				}
			else
				{
				return	0;
				}
			}
		else
			{
			if ( (a + c > x2 - x1) && (b + d > y1 - y2) )
				{
				return	1;
				}
			else
				{
				return	0;
				}
			}
		}
	else
		{
		if ( y1 < y2 )
			{
			if ( (a + c > x1 - x2) && (b + d > y2 - y1) )
				{
				return	1;
				}
			else
				{
				return	0;
				}
			}
		else
			{
			if ( (a + c > x1 - x2) && (b + d > y1 - y2) )
				{
				return	1;
				}
			else
				{
				return	0;
				}
			}
		}
	}

/*
 * Enemy Initialize
 */
void
enemyinit()
	{
	int	i;

	if ( bossflag ) return;
	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag == 0 )
			{
			enemy[i].pat = DAR_ZAKO;
			enemy[i].flag = 1;
			enemy[i].mtype = gametype;
			enemy[i].muteki = 0;
			enemy[i].xsize = 320;
			enemy[i].ysize = 320;
			switch(enemy[i].mtype)
				{
				case	0:
					{
					// A
					enemy[i].x = gamex;
					enemy[i].y = 200;
					enemy[i].hp = 1;
					move0(0,i);
					break;
					}
				case	1:
					{
					// A'
					enemy[i].x = gamex;
					enemy[i].y = 200;
					enemy[i].hp = 1;
					move1(0,i);
					break;
					}
				case	2:
					{
					// B
					enemy[i].x = gamex;
					enemy[i].y = MAXY;
					enemy[i].hp = 1;
					move2(0,i);
					break;
					}
				case	3:
					{
					// B'
					enemy[i].x = gamex;
					enemy[i].y = MAXY;
					enemy[i].hp = 1;
					move3(0,i);
					break;
					}
				case	4:
					{
					// C
					enemy[i].x = gamex;
					enemy[i].y = 200;
					enemy[i].hp = 2;
					move4(0,i);
					break;
					}
				case	5:
					{
					// C'
					enemy[i].x = gamex;
					enemy[i].y = 200;
					enemy[i].hp = 2;
					move5(0,i);
					break;
					}
				case	6:
					{
					// D
					enemy[i].x = gamex;
					enemy[i].y = MAXY;
					enemy[i].hp = 5;
					move6(0,i);
					break;
					}
				case	7:
					{
					// D'
					enemy[i].x = gamex;
					enemy[i].y = MAXY;
					enemy[i].hp = 5;
					move7(0,i);
					break;
					}
				case	8:
					{
					// BONUS
					enemy[i].x = random(2560);
					enemy[i].y = 200;
					enemy[i].hp = 1;
					move8(0,i);
					break;
					}
				case	9:
					{
					// BOSS
					bossflag = 1;
					enemy[i].x = 1920;
					enemy[i].y = 200;
					enemy[i].hp = 300;
					enemy[i].pat = DAR_BOSS;
					enemy[i].xsize = 640;
					enemy[i].ysize = 640;
					move9(0,i);
					break;
					}
				case	10:
					{
					// ROCK
					enemy[i].x = random(2560);
					enemy[i].y = 200;
					enemy[i].hp = 10000;
					enemy[i].pat = DAR_ZAKO+8;
					move10(0,i);
					break;
					}
				}
			break;
			}
		}
	}

/*
 * Enmey Control
 */
void
enemycontrol()
	{
	int	i,j,k;
	int	a,b,c,d;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			if ( enemy[i].flag > 1 )
				{
				if ( aflag%2 == 0 ) enemy[i].flag++;
				if ( enemy[i].flag > 9 ) enemy[i].flag = 0;
				continue;
				}
			switch(enemy[i].mtype)
				{
				case	0:
					{
					move0(1,i);
					break;
					}
				case	1:
					{
					move1(1,i);
					break;
					}
				case	2:
					{
					move2(1,i);
					break;
					}
				case	3:
					{
					move3(1,i);
					break;
					}
				case	4:
					{
					move4(1,i);
					break;
					}
				case	5:
					{
					move5(1,i);
					break;
					}
				case	6:
					{
					move6(1,i);
					break;
					}
				case	7:
					{
					move7(1,i);
					break;
					}
				case	8:
					{
					move8(1,i);
					break;
					}
				case	10:
					{
					move10(1,i);
					break;
					}
				}
			enemy[i].x += enemy[i].xspeed;
			enemy[i].y += enemy[i].yspeed;
			if ( enemy[i].y > MAXY || enemy[i].y < 200 ) enemy[i].flag = 0;
			if ( enemy[i].x < 0 ) enemy[i].x += 2560;
			if ( enemy[i].x > 2559 ) enemy[i].x -= 2560;
			if ( enemy[i].mtype == 10 )
				{
				if ( aflag%2 == 0 )
					{
					enemy[i].pat++;
					if ( enemy[i].pat > DAR_ZAKO+23 ) enemy[i].pat = DAR_ZAKO+8;
					}
				}
			else if ( enemy[i].mtype != 9 )
				{
				enemy[i].pat++;
				if ( enemy[i].pat > DAR_ZAKO+3 ) enemy[i].pat = DAR_ZAKO;
				}

			// 自機との当たり判定
			enemy[i].muteki--;
			if ( enemy[i].muteki <= 0 ) enemy[i].muteki = 0;

			if ( enemy[i].muteki == 0 && ship.muteki == 0 )
				{
				a = ship.x;
				b = ship.y;
				c = enemy[i].x;
				d = enemy[i].y;
				if ( hitcheck(a,b,120,80,c,d,160,80) )
					{
					ship.muteki = 100;
					ship.flag++;
					pcmplay(ADP_BBAKU);
					enemy[i].hp--;
					if ( enemy[i].hp <= 0 )
						{
						enemy[i].flag++;
						pcmplay(ADP_ZBAKU);
						ship.score += enemy[i].score;
						}
					}
				}
			// 自弾との当たり判定
			for ( j = 0 ; j < MAXMSL ; j++ )
				{
				if ( msl[j].flag )
					{
					a = msl[j].x;
					b = msl[j].y;
					c = enemy[i].x;
					d = enemy[i].y;
					if ( hitcheck(a,b,160,80,c,d,160,80) && enemy[i].muteki == 0 )
						{
						enemy[i].hp--;
						if ( enemy[i].hp <= 0 )
							{
							enemy[i].flag++;
							if ( enemybakucheck() ) hit++;
							pcmplay(ADP_ZBAKU);
							ship.score += enemy[i].score;
							if ( random(10) == 0 ) iteminit(i);
							if ( msl[j].type != 2 )	msl[j].flag = 0;
							}
						}
					}
				}
			enemy[i].x2 = enemy[i].x / 10;
			enemy[i].y2 = enemy[i].y / 10;
			}
		}
	}

/*
 * BOSS Control
 */
void
bosscontrol()
	{
	int	i,j,k;
	int	a,b,c,d;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag )
			{
			if ( enemy[i].flag > 1 )
				{
				if ( aflag%2 == 0 ) enemy[i].flag++;
				if ( enemy[i].flag > 9 ) enemy[i].flag = 0;
				continue;
				}

			move9(1,i);

			if ( enemy[i].hp <= 100 )
				{
				enemy[i].muteki = 100;
				enemy[i].hp--;
				if ( aflag%4 == 0 ) bakuinit(0,i);
				}

			enemy[i].x += enemy[i].xspeed;
			enemy[i].y += enemy[i].yspeed;

			if ( enemy[i].y > MAXY || enemy[i].y < 200 ) enemy[i].flag = 0;
			if ( enemy[i].x < 0 ) enemy[i].x += 2560;
			if ( enemy[i].x > 2559 ) enemy[i].x -= 2560;

			// 自機との当たり判定
			if ( ship.muteki == 0 && enemy[i].muteki == 0 )
				{
				a = ship.x;
				b = ship.y;
				c = enemy[i].x;
				d = enemy[i].y;
				if ( hitcheck(a,b,120,80,c,d,320,160) )
					{
					ship.muteki = 100;
					ship.flag++;
					pcmplay(ADP_BBAKU);
					enemy[i].hp--;
					}
				}
			// 自弾との当たり判定
			for ( j = 0 ; j < MAXMSL ; j++ )
				{
				if ( msl[j].flag )
					{
					a = msl[j].x;
					b = msl[j].y;
					c = enemy[i].x;
					d = enemy[i].y;
					if ( hitcheck(a,b,160,80,c,d,320,160) && enemy[i].muteki == 0 )
						{
						enemy[i].hp--;
						if ( msl[j].type != 2 )	msl[j].flag = 0;
						}
					}
				}
			if ( enemy[i].hp <= 0 )
				{
				for ( k = 0 ; k < MAXBAKU ; k++ )
					{
					baku[k].flag = 0;
					bakuinit(1,i);
					}
				enemy[i].flag++;
				pcmplay(ADP_BBAKU);
				ship.score += enemy[i].score;
				}
			enemy[i].x2 = enemy[i].x / 10;
			enemy[i].y2 = enemy[i].y / 10;
			}
		}
	}

/*
 * Enemy Missle Control
 */
void
enemymslcontrol()
	{
	int	i;
	int	a,b,c,d;

	for ( i = 0 ; i < MAXENEMYMSL ; i++ )
		{
		if ( enemymsl[i].flag )
			{
			enemymsl[i].x += enemymsl[i].xspeed;
			enemymsl[i].y += enemymsl[i].yspeed;
			if ( enemymsl[i].x < 0 ) enemymsl[i].x += 2560;
			if ( enemymsl[i].x > 2559 ) enemymsl[i].x -= 2560;
			if ( enemymsl[i].y < 200 || enemymsl[i].y > MAXY ) enemymsl[i].flag = 0;
			a = ship.x;
			b = ship.y;
			c = enemymsl[i].x;
			d = enemymsl[i].y;
			if ( hitcheck(a,b,120,80,c,d,80,40) && ship.muteki == 0 )
				{
				ship.muteki = 100;
				ship.flag++;
				pcmplay(ADP_BBAKU);
				enemymsl[i].flag = 0;
				}
			enemymsl[i].x2 = enemymsl[i].x / 10;
			enemymsl[i].y2 = enemymsl[i].y / 10;
			}
		}
	}

/*
 * Homing Missle
 */
void
hominginit(int num)
	{
	int	i,j,a;

	for ( i = 0 ; i < MAXHOMING ; i++ )
		{
		if ( homing[i][0].flag == 0 )
			{
			a = 0;
			for ( j = 0 ; j < 10 ; j+= 3 )
				{
				homing[i][j].pat = DAR_SHOT + 3 + a;
				a++;
				}
			for ( j = 0 ; j < 10 ; j++ )
				{
				homing[i][j].flag = 1;
				homing[i][j].x = enemy[num].x;
				homing[i][j].y = enemy[num].y;
				}
			break;
			}
		}
	}

/*
 * Homing Control
 */
void
homingcontrol()
	{
	int	i,j;
	int	a,b,c,d;

	for ( i = 0 ; i < MAXHOMING ; i++ )
		{
		if ( homing[i][0].flag )
			{
			for ( j = 9 ; j > 0 ; j-- )
				{
				homing[i][j].x = homing[i][j-1].x;
				homing[i][j].y = homing[i][j-1].y;
				}
			a = homing[i][0].x - ship.x;
			if ( a > 0 && a <= 1280 )
				{
				homing[i][0].x -= 10;
				}
			else if ( a > 1280 )
				{
				homing[i][0].x += 10;
				}
			else if ( a < 0 && a >= -1280 )
				{
				homing[i][0].x += 10;
				}
			else if ( a < -1280 )
				{
				homing[i][0].x -= 10;
				}
			homing[i][0].y += 10;
			if ( homing[i][0].x < 0 ) homing[i][0].x += 2560;
			if ( homing[i][0].x > 2559 ) homing[i][0].x -= 2560;
			if ( homing[i][0].y < 200 || homing[i][0].y > MAXY ) homing[i][0].flag = 0;
			a = ship.x;
			b = ship.y;
			c = homing[i][0].x;
			d = homing[i][0].y;
			if ( hitcheck(a,b,120,80,c,d,80,40) && ship.muteki == 0 )
				{
				ship.muteki = 100;
				ship.flag++;
				pcmplay(ADP_BBAKU);
				homing[i][0].flag = 0;
				}
			for ( j = 0 ; j < 10 ; j++ )
				{
				homing[i][j].flag = homing[i][0].flag;
				homing[i][j].x2 = homing[i][j].x / 10;
				homing[i][j].y2 = homing[i][j].y / 10;
				}
			}
		}
	}

/*
 * Star Control
 */
void
starcontrol()
	{
	int	i;

	for ( i = 0 ; i < MAXSTAR ; i++ )
		{
		star[i].y += star[i].yspeed;
		if ( star[i].y > 2200 )
			{
			star[i].x = random(2560);
			star[i].y = 200;
			star[i].xspeed = 0;
			star[i].yspeed = random(30) + 10;
			}
		star[i].x2 = star[i].x / 10;
		star[i].y2 = star[i].y / 10;
		}
	}

/*
 * ZakoA
 */
void move0(int mode, int num)
	{
	int	dat[20][3]={
		0,10,60, 5,5,10, 10,5,10, 15,5,10, 20,5,10, 25,5,10, 20,5,10, 15,5,10,
		10,5,10, 5,5,10, 0,10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 100;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 && enemy[num].y < 1280 )
			{
			enemyshot(enemy[num].x,enemy[num].y,ship.x,ship.y);
			}
		}
	}

/*
 * ZakoA'
 */
void move1(int mode, int num)
	{
	int	dat[20][3]={
		0,10,60, 5,5,10, 10,5,10, 15,5,10, 20,5,10, 25,5,10, 20,5,10, 15,5,10,
		10,5,10, 5,5,10, 0,10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 100;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = -dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = -dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 && enemy[num].y < 1280 )
			{
			enemyshot(enemy[num].x,enemy[num].y,ship.x,ship.y);
			}
		}
	}

/*
 * ZakoB
 */
void move2(int mode, int num)
	{
	int	dat[20][3]={
		0,-15,35, 5,-5,10, 10,-5,10, 15,-5,10, 10,-5,10,
		5,-5,10, 0,-5,10, -5,-5,10, -10,0,10, -15,0,10,
		-10,0,10, -5,0,10, 0,0,10, 5,5,10, 10,10,10,
		15,15,10, 10,10,10, 5,5,10, 0,0,10, 0,-10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 300;
		enemy[num].muteki = 30;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 )
			{
			enemyshot2(enemy[num].x,enemy[num].y,0,tspeed);
			}
		}
	}

/*
 * ZakoB'
 */
void move3(int mode, int num)
	{
	int	dat[20][3]={
		0,-15,35, 5,-5,10, 10,-5,10, 15,-5,10, 10,-5,10,
		5,-5,10, 0,-5,10, -5,-5,10, -10,0,10, -15,0,10,
		-10,0,10, -5,0,10, 0,0,10, 5,5,10, 10,10,10,
		15,15,10, 10,10,10, 5,5,10, 0,0,10, 0,-10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 300;
		enemy[num].muteki = 30;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = -dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = -dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 )
			{
			enemyshot2(enemy[num].x,enemy[num].y,0,tspeed);
			}
		}
	}

/*
 * ZakoC
 */
void move4(int mode, int num)
	{
	int	dat[10][3]={
		0,28,40, 0,0,20, 20,0,30, 0,0,20, 0,-10,30,
		0,0,20,	-20,0,160, 0,0,20, 0,20,999};

	if ( mode == 0 )
		{
		enemy[num].score = 500;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 && enemy[num].y < 1280 )
			{
			enemyshot(enemy[num].x,enemy[num].y,ship.x,ship.y);
			}
		}
	}

/*
 * ZakoC'
 */
void move5(int mode, int num)
	{
	int	dat[10][3]={
		0,28,40, 0,0,20, 20,0,30, 0,0,20, 0,-10,30,
		0,0,20,	-20,0,160, 0,0,20, 0,20,999};

	if ( mode == 0 )
		{
		enemy[num].score = 500;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = -dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = -dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 && enemy[num].y < 1280 )
			{
			enemyshot(enemy[num].x,enemy[num].y,ship.x,ship.y);
			}
		}
	}

/*
 * ZakoD
 */
void move6(int mode, int num)
	{
	int	dat[15][3]={
		-10,-10,40, 0,0,20, 10,-10,20, 0,0,20, -10,-10,20,
		0,0,20,	10,-10,20, 0,0,20, -10,-10,20, 0,0,20,
		10,-10,20, 0,0,20, 0,-10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 1000;
		enemy[num].muteki = 50;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 )
			{
			enemyshot2(enemy[num].x,enemy[num].y,0,tspeed);
			}
		}
	}

/*
 * ZakoD'
 */
void move7(int mode, int num)
	{
	int	dat[15][3]={
		-10,-10,40, 0,0,20, 10,-10,20, 0,0,20, -10,-10,20,
		0,0,20,	10,-10,20, 0,0,20, -10,-10,20, 0,0,20,
		10,-10,20, 0,0,20, 0,-10,999};

	if ( mode == 0 )
		{
		enemy[num].score = 1000;
		enemy[num].muteki = 50;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = -dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		enemy[num].mcount--;
		if ( enemy[num].mcount < 0 )
			{
			enemy[num].mcount2++;
			enemy[num].xspeed = -dat[enemy[num].mcount2][0];
			enemy[num].yspeed = dat[enemy[num].mcount2][1];
			enemy[num].mcount = dat[enemy[num].mcount2][2];
			}
		if ( random(shotrate) == 0 )
			{
			enemyshot2(enemy[num].x,enemy[num].y,0,tspeed);
			}
		}
	}

/*
 * BOSS
 */
void move9(int mode, int num)
	{
	int dat[60][3]={
		0,20,60, 0,-5,40,	// 1
		0,0,20, -10,0,20, 0,0,20, 10,0,40,	// 5
		0,0,20, -10,0,20, 0,0,20, 10,0,20,	// 9
		0,0,20, -10,0,40, 0,0,20, 20,-5,70,	// 13
		0,0,20,	-10,0,20, 0,0,20, 10,0,40,	// 17
		0,0,20, -10,0,20, 0,0,20, 10,0,20,	// 21
		0,0,20, -10,0,40, 0,0,20, 20,5,70,	// 25
		0,0,20, 10,0,20, 0,0,20, -10,0,40,	// 29
		0,0,20, 10,0,20, 0,0,20, -10,0,20,	// 33
		0,0,20, 10,0,40, 0,0,20, -20,-5,70,	// 37
		0,0,20, 10,0,20, 0,0,20, -10,0,40,	// 41
		0,0,20, 10,0,20, 0,0,20, -10,0,20,	// 45
		0,0,20, 10,0,40, 0,0,20, -20,5,70,	// 49
		0,0,20, 0,-10,20, 0,0,20, 0,20,30, 0,-10,40,	// 54
		0,-5,999};

	if ( mode == 0 )
		{
		enemy[num].score = 30000;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = dat[enemy[num].mcount2][0];
		enemy[num].yspeed = dat[enemy[num].mcount2][1];
		enemy[num].mcount = dat[enemy[num].mcount2][2];
		}
	else
		{
		if ( enemy[num].hp > 100 )
			{
			enemy[num].mcount--;
			if ( enemy[num].mcount < 0 )
				{
				enemy[num].mcount2++;
				if ( enemy[num].mcount2 > 54 ) enemy[num].mcount2 = 2;
				enemy[num].xspeed = dat[enemy[num].mcount2][0];
				enemy[num].yspeed = dat[enemy[num].mcount2][1];
				enemy[num].mcount = dat[enemy[num].mcount2][2];
				}
			if ( enemy[num].mcount2 < 49 )
				{
				if ( enemy[num].mcount%2 == 0 && enemy[num].mcount < 8 )
					{
					enemyshot2(enemy[num].x,enemy[num].y,0,20);
					}
				}
			if ( enemy[num].mcount2 > 13 && enemy[num].mcount2 < 25 )
				{
				if ( enemy[num].mcount == 0 )
					{
					hominginit(num);
					}
				}
			if ( enemy[num].mcount2 > 37 && enemy[num].mcount2 < 49 )
				{
				if ( enemy[num].mcount == 0 )
					{
					hominginit(num);
					}
				}
			}
		else
			{
			enemy[num].xspeed = 0;
			enemy[num].yspeed = 0;
			}
		}
	}

/*
 * ZakoZ
 */
void move8(int mode, int num)
	{
	if ( mode == 0 )
		{
		enemy[num].score = 100;
		enemy[num].mcount2 = 0;
		if ( random(2) == 0 )
			{
			enemy[num].xspeed = stage*5 + 10;
			}
		else
			{
			enemy[num].xspeed = -(stage*5 + 10);
			}
		enemy[num].yspeed = stage + 3;
		enemy[num].mcount = 999;
		}
	}

/*
 * ZakoY
 */
void move10(int mode, int num)
	{
	int	a;

	if ( mode == 0 )
		{
		a = 6 + stage*2;
		enemy[num].score = 100;
		enemy[num].mcount2 = 0;
		enemy[num].xspeed = random(a) - random(a);
		enemy[num].yspeed = random(a) + 5;
		enemy[num].mcount = 999;
		}
	}

/*
 * Item Initialize
 */
void
iteminit(int num)
	{
	int	i;

	for ( i = 0 ; i < MAXITEM ; i++ )
		{
		if ( item[i].flag == 0 )
			{
			item[i].flag = 1;
			item[i].x = enemy[num].x;
			item[i].y = enemy[num].y;
			item[i].xspeed = 0;
			item[i].yspeed = 10;
			item[i].type = random(3);
			item[i].pat = item[i].type + DAR_SHOT + 9;
			item[i].x2 = item[i].x / 10;
			item[i].y2 = item[i].y / 10;
			break;
			}
		}
	}

/*
 * Item Control
 */
void
itemcontrol()
	{
	int	i,j;
	int	a,b,c,d;

	for ( i = 0 ; i < MAXITEM ; i++ )
		{
		if ( item[i].flag )
			{
			item[i].x += item[i].xspeed;
			item[i].y += item[i].yspeed;
			if ( item[i].y > MAXY ) item[i].flag = 0;
			item[i].x2 = item[i].x / 10;
			item[i].y2 = item[i].y / 10;

			a = ship.x;
			b = ship.y;
			c = item[i].x;
			d = item[i].y;
			if ( hitcheck(a,b,160,80,c,d,80,80) && ship.flag == 1 )
				{
				for ( j = 0 ; j < MAXMSL ; j++ )
					{
					msl[j].flag = 0;
					}
				pcmplay(ADP_ITEM);
				item[i].flag = 0;
				ship.type = ship.mtype = item[i].type;
				ship.score += 100;
				}
			}
		}
	}

/*
 * 敵弾発射; 自機を狙う弾
 */
void
enemyshot(int x1,int y1,int x2,int y2)
	{
	int	i,j;
	int	a,b,c;
	int	dx,dy;

	for ( i = 0 ; i < MAXENEMYMSL ; i++ )
		{
		if ( enemymsl[i].flag == 0 )
			{
			enemymsl[i].flag = 1;
			enemymsl[i].x = x1;
			enemymsl[i].y = y1;
			dx = x2 - x1;
			dy = y2 - y1;
			a = abs(dx);
			b = abs(dy);
			if ( dx == 0 )
				{
				enemymsl[i].xspeed = 0;
				if ( dy < 0 )
					{
					enemymsl[i].yspeed = -tspeed;
					}
				else
					{
					enemymsl[i].yspeed = tspeed;
					}
				}
			else if ( dy == 0 )
				{
				enemymsl[i].yspeed = 0;
				if ( dx < 0 )
					{
					enemymsl[i].xspeed = -tspeed;
					}
				else
					{
					enemymsl[i].xspeed = tspeed;
					}
				}
			else if ( a > b )
				{
				c = dy*tspeed;
				enemymsl[i].yspeed = c / a;
				if ( dx < 0 )
					{
					enemymsl[i].xspeed = -tspeed;
					}
				else
					{
					enemymsl[i].xspeed = tspeed;
					}
				}
			else
				{
				c = dx*tspeed;
				enemymsl[i].xspeed = c / b;
				if ( dy < 0 )
					{
					enemymsl[i].yspeed = -tspeed;
					}
				else
					{
					enemymsl[i].yspeed = tspeed;
					}
				}
			enemymsl[i].pat = DAR_SHOT + 2;
			enemymsl[i].type = 0;
			enemymsl[i].xsize = 160;
			enemymsl[i].ysize = 160;
			}
		}
	}

/*
 * 敵弾発射; 決まった方向の弾
 */
void
enemyshot2(int x,int y,int xs,int ys)
	{
	int	i,j;
	int	dx,dy;

	for ( i = 0 ; i < MAXENEMYMSL ; i++ )
		{
		if ( enemymsl[i].flag == 0 )
			{
			enemymsl[i].flag = 1;
			enemymsl[i].x = x;
			enemymsl[i].y = y;
			enemymsl[i].xspeed = xs;
			enemymsl[i].yspeed = ys;
			enemymsl[i].pat = DAR_SHOT+2;
			enemymsl[i].type = 1;
			enemymsl[i].xsize = 160;
			enemymsl[i].ysize = 160;
			}
		}
	}

/*
 * 敵のタイプを決める
 */
void
getgametype()
	{
	if ( stage < 2 )
		{
		// A A'
		gametype = random(2);
		}
	else if ( stage == 2 )
		{
		// ROCK
		gametype = 8;
		}
	else if ( stage > 2 && stage < 5 )
		{
		// A A' B B'
		gametype = random(4);
		}
	else if ( stage == 5 )
		{
		gametype = 10;
		}
	else if ( stage > 5 && stage < 8 )
		{
		// A A' B B' C C'
		gametype = random(6);
		}
	else if ( stage == 8 )
		{
		gametype = 8;
		}
	else if ( stage > 8 && stage < 11 )
		{
		// A A' B B' C C' D D'
		gametype = random(8);
		}
	else if ( stage == 11 )
		{
		gametype = 10;
		}
	else if ( stage == 12 )
		{
		// BOSS
		gametype = 9;
		}
	}

/*
 * 文字列表示
 */
void
StrDsp(int x,int y,unsigned char *str)
	{
	int	c;
	int	sx,sy;

	c = 0;
	sx = x;
	sy = y;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] > 0x20 )
			{
			sprput(sx,sy,0,256,str[c]);
			}
		sx += 8;
		if ( sx > 255 || str[c] == '\n' )
			{
			sx = x;
			sy += 8;
			}
		c++;
		}
	}

/*
 * 数値を表示する
 */
void
NumDsp(int x,int y,unsigned long val)
	{
	static char dectbl[] = "0123456789";
	static char str[12];
	int i,a,c;

	str[10] = '\0';
	for ( i = 9 ; i >= 0 ; i--)
		{
		str[i] = dectbl[val % 10];
		val /= 10;
		}
	c = a = i = 0;
	while(1)
		{
		if ( str[c] == 0x00 ) break;
		if ( str[c] != '0' || c == 9 ) a = 1;
		if ( a == 1 )
			{
			sprput(x+i*8,y,0,256,str[c]);
			i++;
			}
		c++;
		}
	}

/*
 * 爆発中の敵がいるかどうか
 */
int
enemybakucheck()
	{
	int	i,a;

	for ( i = 0 ; i < MAXENEMY ; i++ )
		{
		if ( enemy[i].flag > 1 ) return	1;
		}
	return	0;
	}

/*
 * 爆発初期化
 */
void
bakuinit(int mode,int num)
	{
	int	i;

	pcmplay(ADP_ZBAKU);
	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag == 0 )
			{
			baku[i].flag = 1;
			if ( mode == 0 )
				{
				baku[i].x = enemy[num].x + random(320)-random(320);
				baku[i].y = enemy[num].y + random(320)-random(320);
				baku[i].xspeed = 0;
				baku[i].yspeed = 0;
				}
			else
				{
				baku[i].x = enemy[num].x;
				baku[i].y = enemy[num].y;
				baku[i].xspeed = random(80) - random(80);
				baku[i].yspeed = random(80) - random(80);
				}
			baku[i].x2 = baku[i].x / 10;
			baku[i].y2 = baku[i].y / 10;
			baku[i].pat = DAR_BAKU;
			break;
			}
		}
	}

/*
 * 爆発コントロール
 */
void
bakucontrol()
	{
	int	i;

	for ( i = 0 ; i < MAXBAKU ; i++ )
		{
		if ( baku[i].flag )
			{
			if ( aflag%2 == 0 ) baku[i].flag++;
			if ( baku[i].flag > 8 ) baku[i].flag = 0;
			baku[i].x += baku[i].xspeed;
			baku[i].y += baku[i].yspeed;
			if ( baku[i].y > MAXY || baku[i].y < 200 ) baku[i].flag = 0;
			if ( baku[i].x < 0 ) baku[i].x += 2560;
			if ( baku[i].x > 2559 ) baku[i].x -= 2560;
			baku[i].x2 = baku[i].x / 10;
			baku[i].y2 = baku[i].y / 10;
			}
		}
	}

/*
 * One Hit check
 */
int
onehitcheck()
	{
	if ( ship.score > oscore )
		{
		return	1;
		}
	else
		{
		return	0;
		}
	}

/*
 * Title
 */
void
title()
	{
	int	a;

	dspwait();
	kingdsp(2);
	randomseed = 0;
	while(1)
		{
		a++;
		if ( a > 60 ) a = 0;
		randomseed++;
		get_pad();
		if ( pad00.KD_TRG & KP_run || pad00.KD_TRG & KP_1 ) break;
//		StrDsp(16,72,"DAGYRUSS");
//		StrDsp(16,200,"(C)NEC Home Electronics,Ltd.");
		StrDsp(16,210,"(C)1996 Bio100%");
		if ( a < 40 ) StrDsp(120,140,"PUSH RUN BUTTON");
		dspwait();
		}
	pcmplay(ADP_COIN);
	maxhit = 0;
	stage = 0;
	loop = 0;
	ship.score = 0;
	bossflag = 0;
	ship.type = ship.mtype = 0;
	left = 3;
	overcount = 0;
	gamemain();
	}

/*
 * KINGに描画
 */
void
kingload(int num, unsigned char *filename)
	{
	int	fp;

	// ファイル読込
	pio_putstr( "BG data loading..." );
	if ( (fp = pio_fopen(filename, "rb")) == -1 )
		{
		pio_putstr("ファイルが開けません。\n");
		return;
		}
	pio_fread(fp,122880,KingFile[num]);
	pio_fclose(fp);
	pio_putstr( "done.\n" );
	}

/*
 * KingDsp
 */
void
kingdsp(int num)
	{
	KINGDispOff();
	KINGScreen(0);
	KINGCls(KING_BG0);
	KINGTrans(KING_BG0,KingFile[num],2);
	KINGDispOn();
	}

/*
 * ADPCMファイルの読込
 */
int
adpload(int num, unsigned char *filename)
	{
	int	fh;

	// ファイルオープン
	if ( (fh = pio_fopen(filename, "rb")) == -1 )
		{
		pio_putstr("ファイルが開けません。\n");
		return	0;
		}
	// ヘッダーの読み込み
	if ( pio_fread(fh,sizeof(ADPFILEHEAD),&aFileHead[num])
		!= sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルフォーマット異常\n");
		pio_fclose(fh);
		return	0;
		}
	if ( aFileHead[num].afFileID != ID_RIFF || aFileHead[num].afFileType
		!= ID_WAVE || aFileHead[num].afFormatID != ID_FMT  )
		{
		pio_putstr("ヘッダーが異常です。\n");
		pio_fclose(fh);
		return 0;
		}
	// データの読み込み
	pio_putstr("ADPCM DATA Loading...\n");
	pio_fseek(fh,0,0);		// ファイルの先頭に移動
	// ヘッダーに書いてあるサイズ + ヘッダー分読み込む
	if ( pio_fread(fh, aFileHead[num].afDataSize + sizeof(ADPFILEHEAD)
		,pcmbuffer) != aFileHead[num].afDataSize + sizeof(ADPFILEHEAD) )
		{
		pio_putstr("ファイルの長さが異常です。\n");
		pio_fclose(fh);
		return	0;
		}
	// データをKRAMに転送し、構造体にパラメータをセットする
	pcmblock += AdpcmDataSet(&pInfo[num], (unsigned short *)pcmbuffer,
									(unsigned short)pcmblock, PCM_NORMAL);
	pio_fclose(fh);
//	AdpcmPlay(CHANNEL_1,&pInfo[num]);
//	AdpcmWait(CHANNEL_1);
	return	1;
	}

/*
 * PCM Play
 */
void pcmplay(int num)
	{
	if ( pcmch == 0 )
		{
		AdpcmStop(CHANNEL_1);
		AdpcmPlay(CHANNEL_1,&pInfo[num]);
		pcmch = 1;
		}
	else
		{
		AdpcmStop(CHANNEL_2);
		AdpcmPlay(CHANNEL_2,&pInfo[num]);
		pcmch = 0;
		}
	}

/*
 * パレット変更
 */
void
PaletteChange(int palettenumber, unsigned short yuv)
	{
	unsigned short	dat[2];

	dat[0] = yuv;
	write_pallet_datas(palettenumber, &dat[0], 1);
	}

/*
 * パレット変更2
 */
void
PaletteChangeBW(int mode,int start,int end)
	{
	int	i;
	unsigned short	dat[2]={0x0088,0xff88};

	if ( mode == 0 )
		{
		// 真っ黒
		for ( i = start ; i < end+1 ; i++ )
			{
			write_pallet_datas(i, &dat[0], 1);
			}
		}
	else
		{
		// 真っ白
		for ( i = start ; i < end+1 ; i++ )
			{
			write_pallet_datas(i, &dat[1], 1);
			}
		}
	}

/*
 * パレットフェードイン、フェードアウト
 */
void
PaletteFadeBlack(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// fadein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadein
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataBlack(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * パレットホワイトイン、ホワイトアウト
 */
void
PaletteFadeWhite(int mode,int start, int end)
	{
	int	i,j;

	if ( mode )
		{
		// whitein
		for ( i = 0 ; i < FADERATE + 1 ; i++ )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	else
		{
		// fadewhiteout
		for ( i = FADERATE ; i >= 0 ; i-- )
			{
			for ( j = start ; j < end+1 ; j++ )
				{
				MakePaletteDataWhite(i,j);
				}
			if ( buttoncheck() ) return;
			VSyncWait();
			write_pallet_datas(start, workdat, (end-start)+1 );
			}
		}
	}

/*
 * 1ボタンチェック
 */
int
buttoncheck()
	{
	get_pad();
	if ( pad00.KD_DAT & KP_1 )
		{
		skipflag = 1;
		return	1;
		}
	return	0;
	}

/*
 * ウェイト
 */
void
Wait(int c)
	{
	int	i,j;
	int	a,b;

	for ( i = 0 ; i < c ; i++ )
		{
		if ( buttoncheck() ) return;
		VSyncWait();
		}
	}

/*
 * ロゴ表示
 */
void
logodsp()
	{
	int	i,j,k,l;

/*	PaletteFadeBlack(0,0,511);
	Wait(60);
	if ( skipflag ) return;
	// NECロゴ
	for ( i = 0 ; i < 8 ; i++ )
		{
		for ( j = 0 ; j < 8 ; j++ )
			{
			sprput(i*32+16,j*32+16,0,256,DAR_WHITE);
			}
		}
	sprput(128,120,0,256,DAR_NEC);
	dspwait();
	PaletteFadeBlack(1,0,511);
	Wait(120);
	if ( skipflag ) return;
*/	PaletteFadeWhite(0,0,511);
	Wait(60);
	if ( skipflag ) return;

	// Bio100%ロゴ
	for ( i = 0 ; i < FADERATE+1 ; i++ )
		{
		for ( j = 0 ; j < 512 ; j++ )
			{
			MakePaletteDataWhite(i,j);
			}
		if ( buttoncheck() ) return;
		VSyncWait();
		write_pallet_datas(0, workdat, 512);
		for ( k = 0 ; k < 8 ; k++ )
			{
			for ( l = 0 ; l < 8 ; l++ )
				{
				sprput(k*32+16,l*32+16,0,256,DAR_WHITE);
				}
			}
		sprput(128,120,(FADERATE-i)*32,256+(FADERATE-i)*32,DAR_BIO);
		dspwait();
		}
	if ( skipflag ) return;
	Wait(120);
	if ( skipflag ) return;
	PaletteFadeBlack(0,0,511);
	Wait(60);
	}

/*
 * パレットデータ作成
 */
void
MakePaletteDataBlack(int i, int j)
	{
	int	a,b,c,p;

	a = (i5c4yuv_col[j] & 0xff00) * i / FADERATE;
	a &= 0xff00;
	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}

/*
 * パレットデータ作成2
 */
void
MakePaletteDataWhite(int i, int j)
	{
	int	a,b,c;
	unsigned short	p;

	p = i5c4yuv_col[j] & 0xff00;
	a = p + ((0xff00 - p) * (FADERATE-i) / FADERATE);
	a &= 0xff00;

	p = i5c4yuv_col[j] & 0x00f0;
	if ( p > 0x0080 )
		{
		b = 0x0080 + (p - 0x0080) * i / FADERATE;
		}
	else
		{
		b = 0x0080 - (0x0080 - p) * i / FADERATE;
		}
	b &= 0x00f0;
	c = (0x0008 - (i5c4yuv_col[j] & 0xfff0)) * i / FADERATE;
	p = i5c4yuv_col[j] & 0x000f;
	if ( p > 0x0008 )
		{
		c = 0x0008 + (p - 0x0008) * i / FADERATE;
		}
	else
		{
		c = 0x0008 - (0x0008 - p) * i / FADERATE;
		}
	c &= 0x000f;
	workdat[j] = a | b | c;
	}

/*
 * Ending
 */
void
ending()
	{
	int	i,j,a;
	int	ycount;
	unsigned char	*staffdat[200]={
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		"  DAGYRUSS         ",
		" "," "," "," "," "," ",
		"Game Design        ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Program            ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Graphics           ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Ending Sakana       ",
		"          EMI AKIBA",
		" "," "," "," ",
		"Sound              ",
		"     MASAO MASUTANI",
		" "," "," "," ",
		"Special Thanks     ",
		"     ASCIInet bio.*",
		" NIFTY-Serve FGALGL",
		"     NECﾎｰﾑｴﾚｸﾄﾛﾆｸｽ",
		" ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		"Presented by",
		"       Bio100%     ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," ",
		" "," "," "," "," "," "," "," "," "," "
		};

	dspwait();
	kingdsp(1);
	get_pad();
	a = ycount = 0;

	fishinit();
	aflag = 0;

	while(1)
		{
		aflag++;
		if ( aflag > 15 ) aflag = 0;
		// Fish 
		fishdsp();

		for ( i = 0 ; i < 25 ; i++ )
			{
			StrDsp(16,i*20-a,staffdat[ycount+i]);
			}
		a++;
		if ( a > 19 )
			{
			a = 0;
			ycount++;
			if ( ycount > 76 ) break;
			}
		dspwait();
		}

	while(1)
		{
		aflag++;
		if ( aflag > 15 ) aflag = 0;
		// Fish 
		fishdsp();
		for ( i = 0 ; i < 25 ; i++ )
			{
			StrDsp(16,i*20-a,staffdat[ycount+i]);
			}

		get_pad();
		if ( pad00.KD_TRG && KP_1 ) break;
		if ( pad00.KD_TRG && KP_run ) break;
		dspwait();
		}
	}

/*
 * Fish Initialize
 */
void
fishinit()
	{
	ship.x = 1280;
	ship.y = 1280;
	ship.xspeed = random(2) - random(2);
	ship.yspeed = random(2) - random(2);
	ship.type = 2560;	// zoom
	ship.mtype = random(2) - random(2);		// zspeed
	ship.mcount = 0;
	}

/*
 * Fish Control & dsp
 */
void
fishdsp()
	{
	int	r;
	int	xx,yy,zz;

	ship.mcount--;
	if ( ship.mcount <= 0 )
		{
		ship.xspeed = (random(8) - random(8))*3;
		ship.yspeed = (random(5) - random(5))*3;
		ship.mtype = random(20) - random(20);		// zspeed
		ship.mcount = random(20) + 60;
		}
	ship.x += ship.xspeed;
	if ( ship.x < 160 )
		{
		ship.x = 160;
		ship.mcount = 0;
		}
	if ( ship.x > 2500 )
		{
		ship.x = 2500;
		ship.mcount = 0;
		}
	ship.y += ship.yspeed;
	if ( ship.y < 160 )
		{
		ship.y = 160;
		ship.mcount = 0;
		}
	if ( ship.y > 2400 )
		{
		ship.y = 2400;
		ship.mcount = 0;
		}
	ship.type += ship.mtype;
	if ( ship.type < 1280 ) ship.type = 1280;
	if ( ship.type > 2560 ) ship.type = 2560;

	r = ship.yspeed*16;
	xx = ship.x / 10;
	yy = ship.y / 10;
	zz = ship.type / 10;

	if ( ship.xspeed <= 0 )
		{
		r = (3600 - r)%3600;
		sprput(xx, yy, r, zz, DAR_EMI0);
		}
	else
		{
		r = (3600 + r)%3600;
		sprput(xx, yy, r, zz, DAR_EMI1);
		}
	}

